package cc.owoo.godpen.network;

import cc.owoo.godpen.analysis.json.Json;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.charset.StandardCharsets;

/**
 * 对话socket
 * Created by nimensei
 * 2022-05-11 下午 07:02
 **/
public class TalkbackSocket {
    private final Socket socket;// socket对象
    private final InputStream input;// 输入流
    private final OutputStream output;// 输出流

    public TalkbackSocket(Socket socket) throws IOException {
        this.socket = socket;
        this.input = socket.getInputStream();
        this.output = socket.getOutputStream();
    }

    /**
     * 发送字节数据
     *
     * @param bytes 字节数据
     * @throws IOException 发送异常
     */
    public void send(byte[] bytes) throws IOException {
        if (bytes == null)
            throw new NullPointerException("数据不能为空");
        output.write(new byte[]{
                (byte) (bytes.length >> 24),
                (byte) (bytes.length >> 16),
                (byte) (bytes.length >> 8),
                (byte) (bytes.length),
        });
        output.write(bytes);
    }

    /**
     * 发送文本数据
     *
     * @param text 文本数据
     * @throws IOException 发送异常
     */
    public void send(String text) throws IOException {
        if (text == null)
            throw new NullPointerException("数据不能为空");
        send(text.getBytes(StandardCharsets.UTF_8));
    }

    /**
     * 发送json数据
     *
     * @param json json数据
     * @throws IOException 发送异常
     */
    public void send(Json json) throws IOException {
        if (json == null)
            throw new NullPointerException("数据不能为空");
        send(json.stringify().getBytes(StandardCharsets.UTF_8));
    }

    /**
     * 接收字节数据
     *
     * @return 字节数据
     * @throws IOException 接收异常
     */
    public byte[] acceptBytes() throws IOException {
        int length = (input.read() & 0xFF) << 24 |
                (input.read() & 0xFF) << 16 |
                (input.read() & 0xFF) << 8 |
                (input.read() & 0xFF);
        if (length <= 0)
            throw new IOException("内容长度异常: length = " + length);
        byte[] bytes = new byte[length];
        int index = 0;
        while (index < length) {
            int len = input.read(bytes, index, length - index);
            if (len == -1)
                throw new IOException("内容长度异常: length = " + length + ", index = " + index);
            index += len;
        }
        return bytes;
    }

    /**
     * 接收文本数据
     *
     * @return 文本数据
     * @throws IOException 接收异常
     */
    public String acceptText() throws IOException {
        return new String(acceptBytes(), StandardCharsets.UTF_8);
    }

    /**
     * 接收JsonMap数据
     *
     * @return JsonMap数据
     * @throws IOException 接收异常
     */
    public Json acceptJson() throws IOException {
        return Json.parse(acceptText());
    }

    /**
     * 获取Socket对象
     *
     * @return Socket对象
     */
    public Socket getSocket() {
        return socket;
    }

    /**
     * 获取输入流对象
     *
     * @return 输入流对象
     */
    public InputStream getInput() {
        return input;
    }

    /**
     * 获取输出流对象
     *
     * @return 输出流对象
     */
    public OutputStream getOutput() {
        return output;
    }

    /**
     * 关闭socket
     *
     * @throws IOException 关闭异常
     */
    public void close() throws IOException {
        socket.close();
    }
}
